﻿using DimensionsHelper.Common.Contracts.TableFormatter.Options;

namespace DimensionsHelper.Client.WinUi.ViewModels;

public partial class SigComparisonMapViewModel : ObservableCollection<SigComparisonViewModel>
{
    private readonly Dictionary<string, SigComparisonViewModel> _map = [];


    public RelayCommand AddNewCommand => new(() => Add(new SigComparisonViewModel { Map = this }));

    public RelayCommand ClearCommand => new(Clear);


    [GeneratedRegex(@"[\s\/\\]*")]
    private static partial Regex SpaceOrSeparatorRegex();


    private static string GetComparisonMapKey(SigComparison comparison) =>
        $"{comparison.MarkType}|{comparison.MarkColumn}|{comparison.AnotherColumn}|{comparison.CharAtMarkColumnColor}|{comparison.CharAtAnotherColumnColor}";


    private static string GetSimpleKey(SigComparison comparison) =>
        $"{comparison.MarkType}|{comparison.CharAtMarkColumnColor}|{comparison.CharAtAnotherColumnColor}";


    private static void WriteSigComparison(SigComparisonMap map, SigComparisonViewModel viewModel,
        IReportService reportService)
    {
        if (viewModel.Expression.Length < 2)
        {
            reportService.Warn(ResourceKeys.SigTestExpressionIsInvalidMessage.GetLocalized(), viewModel.Expression);
            return;
        }

        string[] exprs = SpaceOrSeparatorRegex()
            .Replace(viewModel.Expression, m => string.IsNullOrWhiteSpace(m.Value) ? "" : ",")
            .Split(',');

        foreach (string expr in exprs)
        {
            if (expr.Length < 2)
            {
                reportService.Warn(ResourceKeys.SigTestExpressionIsTooShortMessage.GetLocalized(), expr);
                continue;
            }

            char a = expr[0];
            char b = expr[1];

            if (!char.IsLetter(a) || !char.IsLetter(b) || a == b)
            {
                reportService.Warn(ResourceKeys.SigTestExpressionIsInvalidMessage.GetLocalized(), expr);
                continue;
            }

            if (!map.TryAdd(a, b, out SigComparison? comp))
            {
                reportService.Warn(ResourceKeys.SigTestExpressionIsExistMessage.GetLocalized(), expr);
                continue;
            }

            comp.MarkType = viewModel.MarkType;
            comp.CharAtMarkColumnColor = viewModel.CharAtMarkColumnColor.ToExcelStyleColor();
            comp.CharAtAnotherColumnColor = viewModel.CharAtAnotherColumnColor.ToExcelStyleColor();
            comp.StartCharactersToSkip = viewModel.StartStringToSkip;
            comp.BorderMarkConflictFlags = viewModel.GetOperationsOnConflict();
        }
    }


    public bool TryWriteOption(SigComparisonMap target, IReportService reportService)
    {
        foreach (SigComparisonViewModel viewModel in this)
        {
            WriteSigComparison(target, viewModel, reportService);
        }

        return true;
    }


    public void LoadOption(SigComparisonMap source)
    {
        Clear();
        _map.Clear();

        foreach (SigComparison comp in source.Comparisons)
        {
            string key = GetComparisonMapKey(comp);
            string simpleKey = GetSimpleKey(comp);

            // 首先检查simpleKey
            // 1. 如果simpleKey存在，key不存在，将ColumnA和ColumnB调换顺序，加入表达式。
            // 2. 如果simpleKey和key都存在，将原始表达式加入到已有表达式中。
            // 3. 如果simpleKey不存在，使用已有SigComparision对象添加新的ViewModel配置对象。

            if (_map.TryGetValue(simpleKey, out SigComparisonViewModel? viewModel))
            {
                viewModel.JoinExpression(
                    _map.TryGetValue(key, out _)
                        ? comp.ExpressionA
                        : comp.ExpressionB);
            }
            else
            {
                viewModel = new SigComparisonViewModel { Map = this };
                Add(viewModel);

                viewModel.JoinExpression(comp.ExpressionA);
                viewModel.MarkType = comp.MarkType;
                viewModel.CharAtMarkColumnColor = comp.CharAtMarkColumnColor.ToWinUiColor();
                viewModel.CharAtAnotherColumnColor = comp.CharAtAnotherColumnColor.ToWinUiColor();
                viewModel.StartStringToSkip = comp.StartCharactersToSkip;
                viewModel.SetOperationsOnConflict(comp.BorderMarkConflictFlags);

                _map.Add(key, viewModel);
                _map.Add(simpleKey, viewModel);
            }
        }
    }
}